package cn.pink.gatesrv.net.socket;

import cn.pink.core.Port;
import cn.pink.core.PortTask;
import cn.pink.core.Session;
import cn.pink.core.support.Log;
import cn.pink.core.support.Utils;
import cn.pink.gatesrv.SessionService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.net.InetSocketAddress;

/**
 * @Author: pink
 * @Date: 2022/10/24 11:29
 */
public class SocketServerHandler extends ChannelInboundHandlerAdapter {
    /** 当前sessionService*/
    private SessionService service;

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        try {
            Channel channel = ctx.channel();
            Port port = Port.getCurrent();

            service = new SessionService(port, new Session(), channel);

            //添加到port中管理, 使用addTask保证线程安全
            port.addTask(new PortTask() {
                @Override
                public void execute(Port port) {
                    port.addService(service);
                }
            });

            Log.gate.info("create socket conn: address={}, gate={}, port={}, sessionId={}", channel.remoteAddress(), port.getNodeId(), port.getId(), service.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        try {
            // 记录数据
            byte[] buff = (byte[])msg;
            // 超度超长返回
            // 消息长度
            int len = Utils.bytesToBigEndian32(buff, 0);
            if (len > 64 * 1024) {
                return;
            }

            //TODO 解密客户端消息  目前不加密  之后一定要加密  要不非常不安全

            service.onChannelRead(buff);
        } catch (Exception e) {
            InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
            Log.error.error("channelRead0 error, ip = " + address.getAddress().getHostAddress() + ", exception = " + e);
            e.printStackTrace();
            ctx.close();
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        try {
            ctx.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        try {
            Channel channel = ctx.channel();
            Port port = Port.getCurrent();

            Log.gate.info("socket conn exception: address={}, gate={}, port={}, sessionId={}, cause={}", channel.remoteAddress(), port.getNodeId(), port.getId(), service.getId(), cause);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        try {
            Channel channel = ctx.channel();
            Port port = Port.getCurrent();

            Log.gate.info("socket conn inactive: address={}, gate={}, port={}, sessionId={}", channel.remoteAddress(), port.getNodeId(), port.getId(), service.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        try {
            Channel channel = ctx.channel();
            Port port = Port.getCurrent();

            port.addTask(new PortTask() {
                @Override
                public void execute(Port port) {
                    service.onChannelClosed();
                }
            });

            Log.gate.info("socket conn close: address={}, gate={}, port={}, sessionId={}", channel.remoteAddress(), port.getNodeId(), port.getId(), service.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
